#include <crt_stdtime.h>


#if (TARGET_OS == OS_WINDOWS)

#include <winsock2.h>
/* FILETIME of Jan 1 1970 00:00:00. */
static const unsigned __int64 epoch = 116444736000000000;

/*
 * timezone information is stored outside the kernel so tzp isn't used anymore.
 *
 * Note: this function is not for Win32 high precision timing purpose. See
 * elapsed_time().
 */

int	 _gettimeofday(struct timeval * tp, struct timezone * tzp)
{
	FILETIME       file_time;
	SYSTEMTIME     system_time;
	ULARGE_INTEGER ularge;

	GetSystemTime(&system_time);
	SystemTimeToFileTime(&system_time, &file_time);
	ularge.LowPart  = file_time.dwLowDateTime;
	ularge.HighPart = file_time.dwHighDateTime;

	tp->tv_sec  = (long) ((ularge.QuadPart - epoch) / 10000000L);
	tp->tv_usec = (long) (system_time.wMilliseconds * 1000);

	return 0;
}

#endif

#if (TARGET_OS == OS_WINDOWS)


#elif  (TARGET_OS == OS_POSIX)

unsigned long GetTickCount()
{
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);

}

#elif  (TARGET_OS == OS_DARWIN)

unsigned long GetTickCount(void)
{
    struct timespec ts;
    if (__builtin_available(macOS 10.12, *)) {
        if (__builtin_available(iOS 10.0, *)) {
            clock_gettime(_CLOCK_MONOTONIC, &ts);
        } else {
            // Fallback on earlier versions
        }
    } else {
        // Fallback on earlier versions
    }
    return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);

}

#endif

struct tm* _localtime_t(const time_t *timep, struct tm *result)
{
#if (TARGET_OS == OS_WINDOWS)
	return (localtime_s(result, timep) == 0) ? result : NULL;
#elif (TARGET_OS == OS_POSIX)
	return localtime_r(timep, result);
#elif (TARGET_OS == OS_DARWIN)
    return localtime_r(timep, result);
#endif
}


#define TIME_FORMAT "%Y-%m-%d %H:%M:%S"

int get_time_t(char* tm, unsigned long len)
{
	rc_assert(len > 1, S_ERROR)
	time_t seconds = 0;
	size_t rc = 0;
	struct tm res;
    s_memset(&res, 0, sizeof(struct tm));
	seconds = time(NULL);
    
    _localtime_t(&seconds, &res);
    
	rc = strftime(tm, len - 1 , TIME_FORMAT, &res);
	return rc > 0 ? S_SUCCESS : S_ERROR;
}
